package org.wheel.plugins.toolkit.sql.capability;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import org.wheel.plugins.toolkit.sql.enums.CompareType;
import org.wheel.plugins.toolkit.sql.helper.SFunction;

import java.util.Collection;
import java.util.List;

/**
 * 2. 比较运算能力
 * 场景：列 ↔ 值
 * 示例：eq(User::getAge, 18)
 * @param <W> 实现类类型
 * @param <T> 实体类对象
 */
public interface LambdaCompare<W extends LambdaCompare<W,T>, T> {

    default <J> W eq(SFunction<J,?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.EQ, col, val);
    }
    default <J> W eq(Boolean condition, SFunction<J,?> col, Object val){
        return compare(condition, CompareType.EQ, col, val);
    }
    default <J> W ne(SFunction<J, ?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.NE, col, val);
    }
    default <J> W ne(Boolean condition, SFunction<J, ?> col, Object val){
        return compare(condition, CompareType.NE, col, val);
    }
    default <J> W gt(SFunction<J, ?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.GT, col, val);
    }
    default <J> W gt(Boolean condition, SFunction<J, ?> col, Object val){
        return compare(condition, CompareType.GT, col, val);
    }
    default <J> W ge(SFunction<J, ?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.GE, col, val);
    }
    default <J> W ge(Boolean condition, SFunction<J, ?> col, Object val){
        return compare(condition, CompareType.GE, col, val);
    }
    default <J> W lt(SFunction<J, ?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.LT, col, val);
    }
    default <J> W lt(Boolean condition, SFunction<J, ?> col, Object val){
        return compare(condition, CompareType.LT, col, val);
    }
    default <J> W le(SFunction<J, ?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.LE, col, val);
    }
    default <J> W le(Boolean condition, SFunction<J, ?> col, Object val){
        return compare(condition, CompareType.LE, col, val);
    }
    default <J> W like(SFunction<J, ?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.LIKE, col, val);
    }
    default <J> W like(Boolean condition, SFunction<J, ?> col, Object val){
        return compare(condition, CompareType.LIKE, col, val);
    }
    default <J> W notLike(SFunction<J, ?> col, Object val){
        return compare(ObjectUtil.isNotNull(val), CompareType.NOT_LIKE, col, val);
    }
    default <J> W notLike(Boolean condition, SFunction<J, ?> col, Object val){
        return compare(condition, CompareType.NOT_LIKE, col, val);
    }
    default <J> W isNull(SFunction<J, ?> col){
        return compare(true, CompareType.IS_NULL, col, null);
    }
    default <J> W isNull(Boolean condition, SFunction<J, ?> col){
        return compare(condition, CompareType.IS_NULL, col, null);
    }
    default <J> W isNotNull(SFunction<J, ?> col){
        return compare(true, CompareType.IS_NOT_NULL, col, null);
    }
    default <J> W isNotNull(Boolean condition, SFunction<J, ?> col){
        return compare(condition, CompareType.IS_NOT_NULL, col, null);
    }
    default <J> W notIn(SFunction<J, ?> col, Object val){
        return compareList(ObjectUtil.isNotNull(val), CompareType.NOT_IN, col, List.of(val));
    }
    default <J> W notIn(Boolean condition, SFunction<J, ?> col, Object val){
        return compareList(condition, CompareType.NOT_IN, col, List.of(val));
    }
    default <J> W in(SFunction<J, ?> col, Collection<?> val){
        return compareList(CollUtil.isNotEmpty(val), CompareType.IN, col, val);
    }
    default <J> W in(Boolean condition, SFunction<J, ?> col, Collection<?> val){
        return compareList(condition, CompareType.IN, col, val);
    }
    default <J>  W notIn(SFunction<J, ?> col, Collection<?> val){
        return compareList(CollUtil.isNotEmpty(val), CompareType.NOT_IN, col, val);
    }
    default <J> W notIn(Boolean condition, SFunction<J, ?> col, Collection<?> val){
        return compareList(condition, CompareType.NOT_IN, col, val);
    }
    default <J, R> W between(SFunction<J, ?> col, R start, R end){
        return compareList(ObjectUtil.isNotNull(start) && ObjectUtil.isNotNull(end), CompareType.BETWEEN, col, List.of(start, end));
    }
    default <J, R> W between(Boolean condition, SFunction<J, ?> col, R start, R end){
        return compareList(condition, CompareType.BETWEEN, col, List.of(start, end));
    }
    default <J, R> W notBetween(SFunction<J, ?> col, R start , R end){
        return compareList(ObjectUtil.isNotNull(start) && ObjectUtil.isNotNull(end), CompareType.NOT_BETWEEN, col,  List.of(start, end));
    }
    default <J, R> W notBetween(Boolean condition, SFunction<J, ?> col, R start, R end){
        return compareList(condition, CompareType.NOT_BETWEEN, col, List.of(start, end));
    }

    /* 统一底层 */
    <J> W compare(boolean condition, CompareType type, SFunction<J,?> col, Object val);

    <J> W compareList(boolean condition, CompareType type, SFunction<J, ?> col, Collection<?> val);
}
